<?php
namespace BP\DTS;
require_once("BP/DA/DBAccess.php");
require_once("BP/DA/DBUrlType.php");
require_once("BP/DA/DataColumn.php");
require_once("BP/DA/DataRow.php");
require_once("BP/DA/DataTable.php");
require_once("BP/DA/DataType.php");
class DataIOEn {
	public $SELECTSQL;	// String
	public $HisDoType;	// DoType
	public $HisRunTimeType;	// RunTimeType
	public $Title;	// String
	public $FromWhere;	// String
	public $FFs;	// FFs
	public $FromTable;	// String
	public $ToTable;	// String
	public $FromDBUrl;	// DBUrlType
	public $ToDBUrl;	// DBUrlType
	public $UPDATEsql;	// String
	public $Note;	// String
	public $DefaultEveryMonth;	// String
	public $DefaultEveryDay;	// String
	public $DefaultEveryHH;	// String
	public $DefaultEveryMin;	// String
	public $FK_Sort;	// String
	private function __init() { // default class members
		$this->SELECTSQL = NULL;
		$this->HisDoType = DoType::$UnName;
		$this->HisRunTimeType = RunTimeType::$UnName;
		$this->Title = "未命名数据同�?";
		$this->FromWhere = NULL;
		$this->FFs = NULL;
		$this->FromTable = NULL;
		$this->ToTable = NULL;
		$this->FromDBUrl = $DBUrlType->forValue(0);
		$this->ToDBUrl = $DBUrlType->forValue(0);
		$this->Note = "�?";
		$this->DefaultEveryMonth = "99";
		$this->DefaultEveryDay = "99";
		$this->DefaultEveryHH = "99";
		$this->DefaultEveryMin = "99";
		$this->FK_Sort = "0";
	}
	public function GetNoInDTS () 
	{
		return NULL;
	}
	abstract function DoItInThread (); 
	public static function constructor__ () 
	{
		$me = new self();
		$me->__init();
		return $me;
	}
	public function Directly_String_String_String ($fromSQL, $toPTable, $pk) // [String fromSQL, String toPTable, String pk]
	{
			/* match: String_String */
		$this->Directly_String_String($fromSQL, $toPTable);
		$this->ToDBUrlRunSQL((((((("CREATE INDEX " . $toPTable) . "ID ON ") . $toPTable) . " (") . $pk) . ")"));
	}
	public function Directly_String_String_String_String ($fromSQL, $toPTable, $pk1, $pk2) // [String fromSQL, String toPTable, String pk1, String pk2]
	{
			/* match: String_String */
		$this->Directly_String_String($fromSQL, $toPTable);
		$this->ToDBUrlRunSQL((((((((("CREATE INDEX " . $toPTable) . "ID ON ") . $toPTable) . " (") . $pk1) . ",") . $pk2) . ")"));
	}
	public function Directly_String_String_String_String_String ($fromSQL, $toPTable, $pk1, $pk2, $pk3) // [String fromSQL, String toPTable, String pk1, String pk2, String pk3]
	{
			/* match: String_String */
		$this->Directly_String_String($fromSQL, $toPTable);
		$this->ToDBUrlRunSQL((((((((((("CREATE INDEX " . $toPTable) . "ID ON ") . $toPTable) . " (") . $pk1) . ",") . $pk2) . ",") . $pk3) . ")"));
	}
	public function Directly_String_String ($fromSQL, $toPTable) // [String fromSQL, String toPTable]
	{
		$dt = $this->FromDBUrlRunSQLReturnTable($fromSQL);
		$sql = NULL;
		$sql = (("INSERT INTO " . $toPTable) . "(");
		foreach ($dt->Columns as $dc) 		{
			$sql += ($dc->ColumnName . ",");
		}
		$sql = $sql->substring(0, ($sql->length() - 1));
		$sql += ") VALUES (";
		try 
		{
			$this->ToDBUrlRunSQL((" drop table " . $toPTable));
		}
		catch (\Exception $e)
		{ /* empty */ }
		$createTable = (("CREATE TABLE " . $toPTable) . " (");
		foreach ($dt->Columns as $dc) 		{
			if ($dc->DataType->equals("System.String"))
			{
				$createTable += ($dc->ColumnName . " nvarchar (700) NULL  ,");
			}
			else
				if ((($dc->DataType->equals("System.Int16") || $dc->DataType->equals("System.Int32")) || $dc->DataType->equals("System.Int64")))
				{
					$createTable += ($dc->ColumnName . " int NULL,");
				}
				else
					if ($dc->DataType->equals("System.Decimal"))
					{
						$createTable += ($dc->ColumnName . " decimal NULL,");
					}
					else
					{
						$createTable += ($dc->ColumnName . " float NULL,");
					}
		}
		$createTable = $createTable->substring(0, ($createTable->length() - 1));
		$createTable += ")";
		$this->ToDBUrlRunSQL($createTable);
		$sql2 = NULL;
		$errormsg = "";
		foreach ($dt->Rows as $dr) 		{
			$sql2 = $sql;
			foreach ($dt->Columns as $dc) 			{
				$sql2 += (("'" . $dr->getValue($dc->ColumnName)) . "',");
			}
			$sql2 = ($sql2->substring(0, ($sql2->length() - 1)) . ")");
			try 
			{
				$this->ToDBUrlRunSQL($sql2);
			}
			catch (\RuntimeException $ex)
			{
				$errormsg += $ex->getMessage();
			}
		}
		if (!$errormsg->equals(""))
		{
			throw new \RuntimeException((" data output error: " . $errormsg));
		}
	}
	public function FromDBUrlRunSQLReturnTable ($selectSql) // [String selectSql]
	{
		$dt = new DataTable();
		switch ($this->FromDBUrl) {
			case $AppCenterDSN:
				try 
				{
					$dt = DBAccess->RunSQLReturnTable($selectSql);
				}
				catch (Exception $e)
				{
					$e->printStackTrace();
				}
				break;
			default:
				break;
		}
		return $dt;
	}
	public function ToDBUrlRunSQL ($sql) // [String sql]
	{
		switch ($this->ToDBUrl) {
			case $AppCenterDSN:
				try 
				{
					return DBAccess::RunSQL($sql);
				}
				catch (Exception $e)
				{
					$e->printStackTrace();
				}
			default:
				throw new \RuntimeException("@ error it");
		}
	}
	public function ToDBUrlRunDropTable ($table) // [String table]
	{
		switch ($this->ToDBUrl) {
			default:
				throw new \RuntimeException("@ error it");
		}
	}
	public function ToDBUrlIsExit ($sql) // [String sql]
	{
		switch ($this->ToDBUrl) {
			case $AppCenterDSN:
				try 
				{
					return DBAccess->IsExits($sql);
				}
				catch (Exception $e)
				{
					$e->printStackTrace();
				}
			default:
				throw new \RuntimeException("@ error it");
		}
	}
	public function Do () 
	{
		if (($this->HisDoType == DoType::$UnName))
		{
			throw new \RuntimeException("@没有说明同步的类�?,请在基础信息里面设置同步的类�?(构�?�函数．)�?");
		}
		if (($this->HisDoType == DoType::$DeleteInsert))
		{
			$this->DeleteInsert();
		}
		if (($this->HisDoType == DoType::$Inphase))
		{
			$this->Inphase();
		}
		if (($this->HisDoType == DoType::$Incremental))
		{
			$this->Incremental();
		}
	}
	public function Incremental () 
	{
		$this->DoBefore();
		$FromDataTable = $this->GetFromDataTable();
		$isExitSql = "";
		$InsertSQL = "";
		foreach ($FromDataTable->Rows as $FromDR) 		{
			$isExitSql = (("SELECT * FROM " . $this->ToTable) . " WHERE ");
			foreach ($this->FFs as $ff) 			{
				if (!$ff->IsPK)
				{
					continue;
				}
				$isExitSql += ((($ff->ToField . "='") . $FromDR->getValue($ff->FromField)) . "' AND ");
			}
			$isExitSql = $isExitSql->substring(0, ($isExitSql->length() - 5));
			try 
			{
				if (DBAccess->IsExits($isExitSql))
				{
					continue;
				}
			}
			catch (Exception $e1)
			{
				$e1->printStackTrace();
			}
			$InsertSQL = (("INSERT INTO " . $this->ToTable) . "(");
			foreach ($this->FFs as $ff) 			{
				$InsertSQL += ($ff->ToField . ",");
			}
			$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
			$InsertSQL += ") values(";
			foreach ($this->FFs as $ff) 			{
				if ((($ff->DataType == $DataType->AppString) || ($ff->DataType == $DataType->AppDateTime)))
				{
					$InsertSQL += (("'" . $FromDR->getValue($ff->FromField)) . "',");
				}
				else
				{
					$InsertSQL += ($FromDR->getValue($ff->FromField) . ",");
				}
			}
			$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
			$InsertSQL += ")";
			switch ($this->ToDBUrl) {
				case $AppCenterDSN:
					try 
					{
						DBAccess::RunSQL($InsertSQL);
					}
					catch (Exception $e)
					{
						$e->printStackTrace();
					}
					break;
				default:
					break;
			}
		}
		$this->DoAfter();
	}
	abstract function DoBefore (); 
	abstract function DoAfter (); 
	public function DeleteInsert () 
	{
		$this->DoBefore();
		$FromDataTable = $this->GetFromDataTable();
		$this->DeleteObjData();
		$InsertSQL = "";
		foreach ($FromDataTable->Rows as $FromDR) 		{
			$InsertSQL = (("INSERT INTO " . $this->ToTable) . "(");
			foreach ($this->FFs as $ff) 			{
				$InsertSQL += ($ff->ToField . ",");
			}
			$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
			$InsertSQL += ") values(";
			foreach ($this->FFs as $ff) 			{
				if ((($ff->DataType == $DataType->AppString) || ($ff->DataType == $DataType->AppDateTime)))
				{
					$InsertSQL += (("'" . $FromDR->getValue($ff->FromField)) . "',");
				}
				else
				{
					$InsertSQL += ($FromDR->getValue($ff->FromField) . ",");
				}
			}
			$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
			$InsertSQL += ")";
			switch ($this->ToDBUrl) {
				case $AppCenterDSN:
					try 
					{
						DBAccess::RunSQL($InsertSQL);
					}
					catch (Exception $e)
					{
						$e->printStackTrace();
					}
					break;
				default:
					break;
			}
		}
		$this->DoAfter();
	}
	public function DeleteObjData () 
	{
		switch ($this->ToDBUrl) {
			case $AppCenterDSN:
				DBAccess::RunSQL(("DELETE FROM  " . $this->ToTable));
				break;
			default:
				break;
		}
	}
	public function GetToDataTable () 
	{
		$sql = ("SELECT * FROM " . $this->ToTable);
		$FromDataTable = new DataTable();
		switch ($this->ToDBUrl) {
			case $AppCenterDSN:
				$FromDataTable = DBAccess->RunSQLReturnTable($sql);
				break;
			default:
				throw new \RuntimeException("the to dburl error DBUrlType ");
		}
		return $FromDataTable;
	}
	public function GetFromDataTable () 
	{
		$FromSQL = "SELECT ";
		foreach ($this->FFs as $ff) 		{
			if (($ff->DataType == $DataType->AppDateTime))
			{
				$FromSQL += (((((((((((((((((" CASE  " . " when datalength( CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " )))=1 then datename(year,") . $ff->FromField) . " )+'-'+('0'+CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " ))) ") . " else ") . " datename(year,") . $ff->FromField) . " )+'-'+CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " )) ") . " END ") . " AS ") . $ff->FromField) . " , ");
			}
			else
			{
				$FromSQL += ($ff->FromField . ",");
			}
		}
		$FromSQL = $FromSQL->substring(0, ($FromSQL->length() - 1));
		$FromSQL += (" from " . $this->FromTable);
		$FromSQL += $this->FromWhere;
		$FromDataTable = new DataTable();
		switch ($this->FromDBUrl) {
			case $AppCenterDSN:
				$FromDataTable = DBAccess->RunSQLReturnTable($FromSQL);
				break;
			default:
				throw new \RuntimeException("the from dburl error DBUrlType ");
		}
		return $FromDataTable;
	}
	public function Inphase () 
	{
		$this->DoBefore();
		$FromSQL = "SELECT ";
		foreach ($this->FFs as $ff) 		{
			if (($ff->DataType == $DataType->AppDateTime))
			{
				$FromSQL += (((((((((((((((((" CASE  " . " when datalength( CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " )))=1 then datename(year,") . $ff->FromField) . " )+'-'+('0'+CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " ))) ") . " else ") . " datename(year,") . $ff->FromField) . " )+'-'+CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " )) ") . " END ") . " AS ") . $ff->FromField) . " , ");
			}
			else
			{
				$FromSQL += ($ff->FromField . ",");
			}
		}
		$FromSQL = $FromSQL->substring(0, ($FromSQL->length() - 1));
		$FromSQL += (" from " . $this->FromTable);
		$FromSQL += $this->FromWhere;
		$FromDataTable = new DataTable();
		switch ($this->FromDBUrl) {
			case $AppCenterDSN:
				$FromDataTable = DBAccess->RunSQLReturnTable($FromSQL);
				break;
			default:
				break;
		}
		$ToSQL = "SELECT ";
		foreach ($this->FFs as $ff) 		{
			if (!$ff->IsPK)
			{
				continue;
			}
			$ToSQL += ($ff->ToField . ",");
		}
		$ToSQL = $ToSQL->substring(0, ($ToSQL->length() - 1));
		$ToSQL += (" FROM " . $this->ToTable);
		$ToDataTable = new DataTable();
		switch ($this->ToDBUrl) {
			case $AppCenterDSN:
				$ToDataTable = DBAccess->RunSQLReturnTable($ToSQL);
				break;
			default:
				break;
		}
		$SELECTSQL = "";
		$InsertSQL = "";
		$UpdateSQL = "";
		$DeleteSQL = "";
		$result = 0;
		foreach ($FromDataTable->Rows as $FromDR) 		{
			$UpdateSQL = (("UPDATE  " . $this->ToTable) . " SET ");
			foreach ($this->FFs as $ff) 			{
				switch ($ff->DataType) {
					case $DataType->AppDateTime:
					case $DataType->AppString:
						$UpdateSQL += ((($ff->ToField . "='") . $FromDR->getValue($ff->FromField)) . "',");
						break;
					case $DataType->AppFloat:
					case $DataType->AppInt:
					case $DataType->AppMoney:
					case $DataType->AppRate:
					case $DataType->AppDate:
					case $DataType->AppDouble:
						$UpdateSQL += ((($ff->ToField . "=") . $FromDR->getValue($ff->FromField)) . ",");
						break;
					default:
						throw new \RuntimeException("没有涉及到的数据类型.");
				}
			}
			$UpdateSQL = $UpdateSQL->substring(0, ($UpdateSQL->length() - 1));
			$UpdateSQL += " WHERE ";
			foreach ($this->FFs as $ff) 			{
				if (!$ff->IsPK)
				{
					continue;
				}
				$UpdateSQL += ((($ff->ToField . "='") . $FromDR->getValue($ff->FromField)) . "' AND ");
			}
			$UpdateSQL = $UpdateSQL->substring(0, ($UpdateSQL->length() - 5));
			switch ($this->ToDBUrl) {
				case $AppCenterDSN:
					$result = DBAccess::RunSQL($UpdateSQL);
					break;
				default:
					break;
			}
			if (($result == 0))
			{
				$InsertSQL = (("INSERT INTO " . $this->ToTable) . "(");
				foreach ($this->FFs as $ff) 				{
					$InsertSQL += ($ff->ToField . ",");
				}
				$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
				$InsertSQL += ") values(";
				foreach ($this->FFs as $ff) 				{
					if ((($ff->DataType == $DataType->AppString) || ($ff->DataType == $DataType->AppDateTime)))
					{
						$InsertSQL += (("'" . $FromDR->getValue($ff->FromField)) . "',");
					}
					else
					{
						$InsertSQL += ($FromDR->getValue($ff->FromField) . ",");
					}
				}
				$InsertSQL = $InsertSQL->substring(0, ($InsertSQL->length() - 1));
				$InsertSQL += ")";
				switch ($this->ToDBUrl) {
					case $AppCenterDSN:
						DBAccess::RunSQL($InsertSQL);
						break;
					default:
						break;
				}
			}
		}
		foreach ($ToDataTable->Rows as $ToDR) 		{
			$SELECTSQL = "SELECT ";
			foreach ($this->FFs as $ff) 			{
				if (!$ff->IsPK)
				{
					continue;
				}
				$SELECTSQL += ($ff->FromField . ",");
			}
			$SELECTSQL = $SELECTSQL->substring(0, ($SELECTSQL->length() - 1));
			$SELECTSQL += ((" FROM " . $this->FromTable) . " WHERE ");
			foreach ($this->FFs as $ff) 			{
				if (!$ff->IsPK)
				{
					continue;
				}
				if (($ff->DataType == $DataType->AppDateTime))
				{
					$SELECTSQL += (((((((((((((((((" case " . " when datalength( CONVERT(NVARCHAR,datepart(month,") . $ff->FromField) . " )))=1 then datename(year,") . $ff->FromField) . " )+'-'+('0'+CONVERT(VARCHAR,datepart(month,") . $ff->FromField) . " ))) ") . " else ") . " datename(year,") . $ff->FromField) . " )+'-'+CONVERT(VARCHAR,datepart(month,") . $ff->FromField) . " )) ") . " END ") . "='") . $ToDR->getValue($ff->ToField)) . "' AND ");
				}
				else
				{
					if (($ff->DataType == $DataType->AppString))
					{
						$SELECTSQL += ((($ff->FromField . "='") . $ToDR->getValue($ff->ToField)) . "' AND ");
					}
					else
					{
						$SELECTSQL += ((($ff->FromField . "=") . $ToDR->getValue($ff->ToField)) . " AND ");
					}
				}
			}
			$SELECTSQL = $SELECTSQL->substring(0, ($SELECTSQL->length() - 5));
			$result = 0;
			switch ($this->FromDBUrl) {
				default:
					break;
			}
			if (($result != 1))
			{
				$DeleteSQL = (("delete FROM  " . $this->ToTable) . " WHERE ");
				foreach ($this->FFs as $ff) 				{
					if (!$ff->IsPK)
					{
						continue;
					}
					if (($ff->DataType == $DataType->AppString))
					{
						$DeleteSQL += ((($ff->ToField . "='") . $ToDR->getValue($ff->ToField)) . "' AND ");
					}
					else
					{
						$DeleteSQL += ((($ff->ToField . "=") . $ToDR->getValue($ff->ToField)) . " AND ");
					}
				}
				$DeleteSQL = $DeleteSQL->substring(0, ($DeleteSQL->length() - 5));
				switch ($this->ToDBUrl) {
					case $AppCenterDSN:
						DBAccess::RunSQL($DeleteSQL);
						break;
					default:
						break;
				}
				continue;
			}
			else
				if (($result > 1))
				{
					throw new \RuntimeException(((("目的数据异常错误＋表名；关键�?" . $this->ToTable) . "关键�?") . $ToDR->getValue(0)));
				}
		}
		if (($this->UPDATEsql != NULL))
		{
			switch ($this->ToDBUrl) {
				case $AppCenterDSN:
					DBAccess::RunSQL($this->UPDATEsql);
					break;
				default:
					break;
			}
		}
		$this->DoAfter();
	}
}
?>
